package org.example.domain.auth.service;


import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.auth.adapter.repository.IAuthRepository;
import org.example.domain.auth.model.entity.UserEntity;
import org.example.types.utils.JwtUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.UUID;


/**
 * @author yinghuashen
 * @version 1.0
 * @description:
 * @date 2025/3/4 10:39
 */
@Slf4j
@Service
public class AuthService implements IAuthService{

    @Resource
    private IAuthRepository authRepository;

    @Override
    public void registerUser(String userName, String userPhone, String userPassword) {
        // 创建 UserEntity 实例
        UserEntity userEntity = new UserEntity();
        userEntity.setUserId(UUID.randomUUID().toString());
        userEntity.setUserName(userName);
        userEntity.setUserPhone(userPhone);
        userEntity.setUserPassword(encrypt(userPassword));
        authRepository.insertUser(userEntity);
    }

    @Override
    public boolean loginByPwd(String phone, String userPassword) {
        // TODO 设置缓存，不走数据库
        UserEntity user = authRepository.getUserBasicInfoByPhone(phone);
        if (user == null) {
            log.info("用户不存在");
            return false;
        }
        return verify(userPassword, user.getUserPassword());
    }

    @Override
    public String loginByCode(String phone, String code) {
        // 1.校验验证码
        String cacheCode = authRepository.getCachedCode(phone);
        if (cacheCode == null || !cacheCode.equals(code)) {
            return null;
        }

        String jwtToken = authRepository.getUserToken(phone);
        if (jwtToken != null) {
            // 刷新token有效期时间
            authRepository.refreshUserJWTToken(phone);
            return jwtToken;
        }

        // 2. 登录成功，使用JWT生成token，返回token和redis中
        jwtToken = JwtUtils.createToken(phone);
        UserEntity userBasicInfo = authRepository.getUserBasicInfoByPhone(phone);
        Map<String, Object> userBasicInfoMap = userBasicInfo.toMap();

        String token = RandomUtil.randomNumbers(6);

        // 3. 将token和用户信息存入redis
        authRepository.saveUserInfoIntoCache(token, userBasicInfoMap);
        // 5. 返回token
        return jwtToken;
    }

    @Override
    public boolean requestCode(String phone) {
        // 1.校验手机号是否存在
        UserEntity user = authRepository.getUserPwdByPhone(phone);
        if (user == null) {
            log.info("用户不存在");
            return false;
        }
        // 3.符合，生成验证码
        String code = RandomUtil.randomNumbers(6);
        // 4.保存验证码到 Redis 中
        authRepository.saveCode(phone, code);
        // 5.发送验证码到手机
        log.info("验证码：{}", code);
        return true;
    }

    @Override
    public String checkUserOnlineState(String phone) {
        return authRepository.getUserToken(phone);
    }

    @Override
    public UserEntity getUserBasicInfoByToken(String token) {
        Map<String, String> userBasicInfoMap = authRepository.getUserBasicInfoByToken(token);
        if (userBasicInfoMap == null) {
            return null;
        }
        return UserEntity.builder().userId(userBasicInfoMap.get("userId"))
                .userName(userBasicInfoMap.get("userName"))
                .userPhone(userBasicInfoMap.get("userPhone"))
                .build();
    }


    /**
     * 对明文字符串进行 MD5 加密
     * @param plainText 明文字符串
     * @return 加密后的十六进制字符串
     */
    private String encrypt(String plainText) {
        try {
            // 获取 MD5 算法实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将明文字符串转换为字节数组并进行摘要计算
            byte[] digest = md.digest(plainText.getBytes(StandardCharsets.UTF_8));
            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            // 若 MD5 算法不可用，抛出运行时异常
            throw new RuntimeException(e);
        }
    }

    /**
     * 验证明文字符串与加密字符串是否匹配
     * @param plainText 明文字符串
     * @param encryptedText 加密后的字符串
     * @return 匹配返回 true，不匹配返回 false
     */
    private boolean verify(String plainText, String encryptedText) {
        // 对明文字符串进行加密
        String encryptedPlainText = encrypt(plainText);
        // 比较加密后的明文字符串与传入的加密字符串
        return encryptedPlainText.equals(encryptedText);
    }

}